package com.wanban.downloader

import android.app.Application
import android.content.Intent
import android.text.TextUtils
import android.util.Log
import androidx.annotation.IntRange
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.Utils
import com.wanban.downloader.db.DatabaseUtils
import com.wanban.downloader.db.DownloadEntity
import com.wanban.downloader.db.room.DownloadRoomUtils
import com.wanban.downloader.db.v3.DatabaseManager
import com.wanban.downloader.db.v3.DownloadSQLiteHelper
import com.wanban.downloader.listener.OnDownloadListener
import com.wanban.downloader.manager.BaseDownloadManager
import com.wanban.downloader.manager.DownloadManager
import com.wanban.downloader.manager.TXDownloadManager
import com.wanban.downloader.model.DownloadParams
import com.wanban.downloader.model.DownloadType
import com.wanban.downloader.service.DownloadService
import com.wanban.downloader.utils.Constants
import com.wanban.downloader.utils.FileDownloadPathUtils
import com.wanban.downloader.utils.RxUtils
import java.lang.NullPointerException

object MultiDownloadManager: NetworkUtils.OnNetworkStatusChangedListener {

    const val TAG = BaseDownloadManager.TAG
    // 当前的下载类型
    private var currentDownloadType = DownloadType.SELF
    // 下载管理器
//    private lateinit var downloadManager: BaseDownloadManager
//    // 腾讯下载器
//    private lateinit var txDownloadManager: BaseDownloadManager

    private var isDataBaseInitSuccess = false

    private val downloadManagers = ArrayList<BaseDownloadManager>()

    fun init(application: Application,
             @DownloadType downloadType: Int,
             listener: OnDownloadListener?,
             onInitComplete: (hasDownloadingTask : Boolean) -> Unit):MultiDownloadManager {
        currentDownloadType = downloadType
        // 初始化Room数据库
        DownloadRoomUtils.initRoom(application)
        // 初始化数据库
        DatabaseManager.initializeInstance(DownloadSQLiteHelper(application))
        // 交换数据，废弃旧数据表
        Log.e("NewTD", "准备初始化...")
        val startTime = System.currentTimeMillis()
        DatabaseUtils.exchangeDatabase { tasks ->
            isDataBaseInitSuccess = true

            // 初始化2个下载器
            val downloadManager = DownloadManager(object: OnDownloadListener {
                override fun onDownloadStatusChanged(task: DownloadEntity) {
                    listener?.onDownloadStatusChanged(task)
                }
            })
            val txDownloadManager = TXDownloadManager(object: OnDownloadListener {
                override fun onDownloadStatusChanged(task: DownloadEntity) {
                    listener?.onDownloadStatusChanged(task)
                }
            })

            // 将重置状态后的列表加入当前下载栈
            tasks.forEach {
                if (it.downloadType == DownloadType.TX) {
                    txDownloadManager.addInitTasks(it)
                } else {
                    downloadManager.addInitTasks(it)
                }
            }

            downloadManagers.add(downloadManager)
            downloadManagers.add(txDownloadManager)

            // 注册网络状态
            NetworkUtils.registerNetworkStatusChangedListener(this)
            onInitComplete(tasks.isNotEmpty())
            val endTime = System.currentTimeMillis() - startTime
            Log.e("NewTD", "初始化完成...耗时：$endTime ms")
        }
        return this
    }

    fun resumeAllDownload() {
        val intent = Intent(Utils.getApp(), DownloadService::class.java)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_ACTION, 0)
        Utils.getApp().startService(intent)
    }

    fun startDownload(task: DownloadEntity) {
        val intent = Intent(Utils.getApp(), DownloadService::class.java)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_TASK, task)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_ACTION, 1)
        Utils.getApp().startService(intent)
    }

    fun stopDownload(url: String) {
        val intent = Intent(Utils.getApp(), DownloadService::class.java)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_DOWNLOAD_URL, url)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_ACTION, 2)
        Utils.getApp().startService(intent)
    }

    fun stopAllDownload(){
        val intent = Intent(Utils.getApp(), DownloadService::class.java)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_ACTION, 5)
        Utils.getApp().startService(intent)
    }

    fun resumeDownload(url: String) {
        val intent = Intent(Utils.getApp(), DownloadService::class.java)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_DOWNLOAD_URL, url)
        intent.putExtra(Constants.INTENT_KEY_SERVICE_ACTION, 3)
        Utils.getApp().startService(intent)
    }

    fun deleteDownload(url: String) {
        if (isStartInService()) {
            downloadManagers.forEach {
                it.deleteDownload(url)
            }
        } else {
            val intent = Intent(Utils.getApp(), DownloadService::class.java)
            intent.putExtra(Constants.INTENT_KEY_SERVICE_DOWNLOAD_URL, url)
            intent.putExtra(Constants.INTENT_KEY_SERVICE_ACTION, 4)
            Utils.getApp().startService(intent)
        }
    }


    fun switchDownloadType(@DownloadType downloadType: Int){
        // 如果目标下载方式跟当前一样，忽略
        if (currentDownloadType == downloadType) return
        currentDownloadType = downloadType
    }

    /** 一次下载任务中，允许下载的最大线程数 */
    fun setMaxThreadNumber(@IntRange(from = 1, to = 10) threadCount: Int): MultiDownloadManager{
        DownloadParams.maxThreadNumber = threadCount
        return this
    }

    /** ts下载出错，允许重试的最大次数 */
    fun setMaxRetryTimes(@IntRange(from = 1, to = 5) maxRetryTimes: Int): MultiDownloadManager{
        DownloadParams.maxRetryTimes = maxRetryTimes
        return this
    }

    /** 网络超时 */
    fun setNetworkTimeOut(@IntRange(from = 1000, to = 60000) networkTimeOut: Int): MultiDownloadManager{
        DownloadParams.networkTimeOut = networkTimeOut
        return this
    }

    /** 一次下载任务中，允许出错的上限 */
    fun setMaxErrorTsCount(@IntRange(from = 0, to = 20) maxErrorTsCount: Int): MultiDownloadManager{
        DownloadParams.maxErrorTsCount = maxErrorTsCount
        return this
    }

    /** 任务栈中，允许同时执行下载的任务数上限 */
    fun setMaxDownloadQueueCount(@IntRange(from = 1, to = 10) maxDownloadCount: Int): MultiDownloadManager{
        DownloadParams.maxDownloadQueueCount = maxDownloadCount
        return this
    }
    /** 任务栈中，非完成状态的任务数上限 */
    fun setMaxDownloadStackCount(@IntRange(from = 1, to = 30) maxDownloadStackCount: Int): MultiDownloadManager{
        DownloadParams.maxDownloadStackCount = maxDownloadStackCount
        return this
    }

    /**
     * 该 #downloadType 类型下载已经没有可用下载，对其他下载器查询是否有可用下载
     * @param downloadType 当前类型的下载器，已经没有可用下载
     */
    internal fun readyToNextTask(downloadType: Int) {
        // 任务队列已满，忽略
        downloadManagers.filter { it.getDownloadType() != downloadType }.forEach {
            it.readyToNextTask()
        }
    }

    internal fun getDownloadManager(downloadType: Int): BaseDownloadManager? {
        return downloadManagers.firstOrNull { it.getDownloadType() == downloadType }


//        return if (downloadType == DownloadType.TX) {
//            txDownloadManager
//        } else {
//            downloadManager
//        }
    }

    internal fun getDownloadManager(url: String): BaseDownloadManager?{
        return downloadManagers.firstOrNull {
            it.getTaskByUrl(url) != null
        }
    }

    internal fun getDownloadManagers(): ArrayList<BaseDownloadManager> {
        return downloadManagers
    }


    private var startInService = false

    fun startInService(){
        startInService = true
    }
    fun isStartInService(): Boolean {
        return startInService
    }


    /**
     * 数据库是否初始化完成
     */
    fun isDateBaseInitComplete(): Boolean{
        return isDataBaseInitSuccess
    }
    /**
     * 返回当前下载器的类型
     */
    fun getCurrentDownloadType(): Int {
        return currentDownloadType
    }

    /**
     * 返回当前队列中，可以启动下载的任务
     */
    fun getCanStartTasks(): ArrayList<DownloadEntity> {
        val targetList = ArrayList<DownloadEntity>()
        getDownloadManagers().forEach { manager ->
            targetList.addAll(manager.getCanRunningTasks())
        }
        return targetList
    }

    fun getDownloadingFragmentList(): ArrayList<DownloadEntity>{
        val targetList = ArrayList<DownloadEntity>()
        getDownloadManagers().forEach { manager ->
            targetList.addAll(manager.getDownloadingFragmentList())
        }
        return targetList
    }

    fun setOnlyWifiDownload(isOnlyWifi: Boolean) {
        downloadManagers.firstOrNull()?.setOnlyWifiDownload(isOnlyWifi)
//        downloadManager.setOnlyWifiDownload(isOnlyWifi)
    }

    fun isOnlyWifiDownload(): Boolean {
//        return downloadManager.isOnlyWifiDownload()
        return downloadManagers.firstOrNull()?.isOnlyWifiDownload()?:true
    }

    fun setDownloadSdcard(isSdcard: Boolean){
//        downloadManager.setDownloadSdcard(isSdcard)
        downloadManagers.firstOrNull()?.setDownloadSdcard(isSdcard)
    }

    fun isDownloadSdcard(): Boolean {
//        return downloadManager.isDownloadSdcard()
        return downloadManagers.firstOrNull()?.isDownloadSdcard()?:false
    }



    /**
     * 当前url是否正在下载中
     * @return true: 任务在下载队列中， false: 不在队列中
     */
    fun isTaskRunning(url: String): Boolean {
//        val task = downloadManager.getTaskByUrl(url)?:return false
//        return downloadManager.isTaskRunning(task)

//        var task = downloadManager.getTaskByUrl(url)
//        if (task != null) { // 当前任务在self下载器中
//            return downloadManager.isTaskRunning(task)
//        }
//        // 在tx下载器中寻找当前任务
//        task = txDownloadManager.getTaskByUrl(url)?:return false
//        return txDownloadManager.isTaskRunning(task)

        return downloadManagers.any {
            return it.isTaskRunning(url)
        }

    }


    /** 获取正在下载的任务数量 */
    fun getRunningTaskCount(): Int {
        var runningTaskCount = 0
        getDownloadManagers().forEach { manager ->
            val currentTask = manager.getRunningTaskList()
            runningTaskCount += currentTask.size
        }
        return runningTaskCount
    }

//    /** 获取下载队列中所有任务总数量 */
//    fun getDownloadQueueCount(): Int {
//        var runningTaskCount = 0
//        getDownloadManagers().forEach { manager ->
//            val currentTask = manager.getRunningTask()
//            runningTaskCount += currentTask.size
//        }
//        return runningTaskCount
//    }

    /** 是否允许新增任务下载 */
    fun isAllowAddNewTask(): Boolean {
        var queueTotalCount = 0
        getDownloadManagers().forEach { manager ->
            queueTotalCount += manager.getCanRunningTasks().size
        }
        return queueTotalCount < DownloadParams.maxDownloadStackCount

//        val queueCount = downloadQueue.count { it.state != Status.SUCCESS && it.state != Status.IDLE && it.state != Status.DELETE }
//        return queueCount < DownloadParams.maxDownloadStackCount
    }

    /**
     * 根据videoId，sourceId and episode 获取对应的任务
     */
    fun getTasksByVideoAndSourceIdAndEpisode(video: Long, sourceId: Int, episode: Int, complete: (task: DownloadEntity?) -> Unit) {
        RxUtils.doObservable({
            val selection = DownloadSQLiteHelper.Columns.VIDEO_ID + "=? " +
                    "AND " +
                    DownloadSQLiteHelper.Columns.EPISODE + "=? " +
                    "AND " +
                    DownloadSQLiteHelper.Columns.SOURCE_ID + "=?"
            val tasks = DatabaseUtils.getTask(selection, arrayOf(video.toString(), episode.toString(), sourceId.toString()))
            if (tasks == null){
                it.onError(NullPointerException())
            } else {
                it.onNext(tasks)
            }
        },{
            complete(it)
        },{
            complete(null)
        })
    }


    fun getAllDownloadTasks(complete: (tasks: ArrayList<DownloadEntity>) -> Unit){
        RxUtils.doObservable({
            val tasks = DatabaseUtils.getTasks(null, null)
            if (tasks.isNullOrEmpty()){
                it.onError(NullPointerException())
            } else {
                it.onNext(tasks)
            }
        },{
            if (it.isNullOrEmpty()) {
                complete(ArrayList())
            } else {
                complete(ArrayList(it))
            }
        },{
            complete(ArrayList())
        })
    }

    fun deleteTasks(tasks: List<DownloadEntity>) {
        tasks.forEach { task ->
            downloadManagers.forEach { it.deleteDownload(task.url) }
        }
    }


    fun getCoverImagePath(fileDirPath: String?): String? {
        if (TextUtils.isEmpty(fileDirPath)) return null
        return FileDownloadPathUtils.getCoverFilePath(fileDirPath)
    }

    override fun onDisconnected() {

    }

    override fun onConnected(networkType: NetworkUtils.NetworkType?) {
        if (networkType == null) return
        getDownloadManagers().forEach {
            it.resumeFromNetworkConnected(networkType)
        }
    }
}